import { createApp, defineAsyncComponent, h } from "vue"
import { callFunc, isFunc } from "./tools"
import { NavigationGuardNext, RouteLocationNormalized } from "vue-router"
import { ElConfigProvider } from "element-plus"
import zhCn from 'element-plus/dist/locale/zh-cn'
import { KeyValues } from "./types"

type SubmittedArgs = {
  isEdit?: boolean,
  data?: any,
  form?: KeyValues
}

type ModalProps = {
  [k: string]: any
  onSubmitted?: (params?: SubmittedArgs) => void
}

export const openModal = (vm: any, props?: ModalProps) => {
  if (isFunc(vm)) {
    vm = defineAsyncComponent(vm)
  }

  let app = createApp({
    data () {
      return {
        modelValue: true,
        onClosed: () => {
          this.$emit('closed')
          app._container && app._container.remove()
          app.unmount()
          app = null
        }
      }
    },
    methods: {
      close () {
        this.modelValue = false
      },
      submitted (params: SubmittedArgs = {}) {
        this.close()
        callFunc(props.onSubmitted, params)
      }
    },
    render () {
      return h(ElConfigProvider, { locale: zhCn }, {
        default: () => {
          return h(vm, {
            size: 600,
            width: 420,
            appendToBody: true,
            closeOnClickModal: false,
            ...(props || {}),
            ...this.$data,
            onClose: this.close,
            onSubmitted: this.submitted
          })
        }
      })
    }
  })

  const div = document.createElement('div')
  document.body.appendChild(div)
  app.mount(div)
}

const getAllShowedModalDoms = () => {
  return Array
    .from(document.body.querySelectorAll('.el-overlay'))
    .filter(el => {
      return window.getComputedStyle(el, null).display !== 'none'
    }) as HTMLDivElement[]
}

const closeModal = (el?: HTMLDivElement) => {
  if (el) {
    const btnClose = el.querySelector('.el-dialog__close, .el-drawer__close') as HTMLButtonElement
    if (btnClose) {
      btnClose.click()
      return true
    }
    const btnMsgBoxClose = el.querySelector('.el-message-box__headerbtn') as HTMLButtonElement
    if (btnMsgBoxClose) {
      btnMsgBoxClose.click()
      return true
    }
  }
}

const closeTopModal = () => {
  return closeModal(
    getAllShowedModalDoms()
      .reduce((t, el) => {
        return t && +t.style.zIndex > +el.style.zIndex ? t : el
      }, null)
  )
}

const closeAllModals = () => getAllShowedModalDoms().reverse().forEach(closeModal)

export const navInterceptor = (to: RouteLocationNormalized, next: NavigationGuardNext) => {
  const toPath = to.path || ''
  const isNav = +to.query._nav
  if (toPath.includes('login') || isNav) {
    closeAllModals()
  } else if (closeTopModal()) {
    return next(false)
  }
  next()
}
